package vip.bblog.common.utils;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author <a href="1396513066@qq.com">Yu Yong</a>
 * @version 1.0
 * @date 2019年03月24日 13:57
 * @Description Spring 上下文工具, 可用于获取spring 容器中的Bean
 * @url https://412887952-qq-com.iteye.com/blog/2348445
 */
@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    private static DefaultListableBeanFactory defaultListableBeanFactory;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        SpringContextUtil.applicationContext = applicationContext;
    }

    /**
     * 获取spring容器中的bean,通过bean名称获取
     *
     * @param beanName bean 名称
     * @return Object 返回Object,需要做强制类型转换
     */
    public static Object getBean(String beanName) {
        return applicationContext.getBean(beanName);
    }

    /**
     * 获取spring容器中的bean, 通过bean类型获取
     *
     * @param beanClass bean 类型
     * @param <T>
     * @return T 返回指定类型的bean实例
     */
    public static <T> T getBean(Class<T> beanClass) {
        return applicationContext.getBean(beanClass);
    }

    /**
     * 获取spring容器中的bean, 通过bean名称和bean类型精确获取
     *
     * @param beanName  bean 名称
     * @param beanClass bean 类型
     * @param <T>
     * @return T 返回指定类型的bean实例
     */
    public static <T> T getBean(String beanName, Class<T> beanClass) {
        return applicationContext.getBean(beanName, beanClass);
    }

    /**
     * 向spring容器注入bean，beanName默认为className
     *
     * @param beanClass bean 类型
     * @param <T>
     * @return true false
     */
    public static <T> void registerBean(Class<T> beanClass) {
        SpringContextUtil.registerBean(StringUtils.uncapitalize(beanClass.getSimpleName()), beanClass);
    }

    /**
     * 向spring容器注入bean
     *
     * @param beanName  bean 名称
     * @param beanClass bean 类型
     * @param <T>
     * @return true false
     */
    public static <T> void registerBean(String beanName, Class<T> beanClass) {
        //创建bean信息
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(beanClass);
        defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
    }

    /**
     * 从spring容器移出bean
     * @param beanClass bean 类型
     * @param <T>
     */
    public static <T> void deleteBean(Class<T> beanClass) {
        defaultListableBeanFactory.removeBeanDefinition(StringUtils.uncapitalize(beanClass.getSimpleName()));
    }

    /**
     * 从spring容器移出bean
     * @param beanName bean 名称
     * @param <T>
     */
    public static <T> void deleteBean(String beanName) {
        defaultListableBeanFactory.removeBeanDefinition(beanName);
    }

}
